home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume10 / comobj.lisp / part12 < prev    next >
Encoding:
Text File  |  1987-08-23  |  43.9 KB  |  1,175 lines

  1. Path: uunet!rs
  2. From: rs@uunet.UU.NET (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v10i086:  Common Objects, Common Loops, Common Lisp, Part12/13
  5. Message-ID: <757@uunet.UU.NET>
  6. Date: 3 Aug 87 21:19:32 GMT
  7. Organization: UUNET Communications Services, Arlington, VA
  8. Lines: 1164
  9. Approved: rs@uunet.UU.NET
  10.  
  11. Submitted-by: Roy D'Souza <dsouza%hplabsc@hplabs.HP.COM>
  12. Posting-number: Volume 10, Issue 86
  13. Archive-name: comobj.lisp/Part12
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then unpack
  17. # it by saving it into a file and typing "sh file".  To overwrite existing
  18. # files, type "sh file -c".  You can also feed this as standard input via
  19. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  20. # will see the following message at the end:
  21. #        "End of archive 12 (of 13)."
  22. # Contents:  methods.l
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. if test -f 'methods.l' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'methods.l'\"
  26. else
  27. echo shar: Extracting \"'methods.l'\" \(42046 characters\)
  28. sed "s/^X//" >'methods.l' <<'END_OF_FILE'
  29. X;;;-*-Mode:LISP; Package: PCL; Base:10; Syntax:Common-lisp -*-
  30. X;;;
  31. X;;; *************************************************************************
  32. X;;; Copyright (c) 1985 Xerox Corporation.  All rights reserved.
  33. X;;;
  34. X;;; Use and copying of this software and preparation of derivative works
  35. X;;; based upon this software are permitted.  Any distribution of this
  36. X;;; software or derivative works must comply with all applicable United
  37. X;;; States export control laws.
  38. X;;; 
  39. X;;; This software is made available AS IS, and Xerox Corporation makes no
  40. X;;; warranty about the software, its performance or its conformity to any
  41. X;;; specification.
  42. X;;; 
  43. X;;; Any person obtaining a copy of this software is requested to send their
  44. X;;; name and post office or electronic mail address to:
  45. X;;;   CommonLoops Coordinator
  46. X;;;   Xerox Artifical Intelligence Systems
  47. X;;;   2400 Hanover St.
  48. X;;;   Palo Alto, CA 94303
  49. X;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
  50. X;;;
  51. X;;; Suggestions, comments and requests for improvements are also welcome.
  52. X;;; *************************************************************************
  53. X;;;
  54. X
  55. X(in-package 'pcl)
  56. X
  57. X  ;;   
  58. X;;;;;; Methods
  59. X  ;;   
  60. X
  61. X(ndefstruct (essential-method
  62. X          (:class class)
  63. X          (:conc-name method-))
  64. X  (discriminator nil)
  65. X  (arglist ())
  66. X  (type-specifiers ())
  67. X  (function nil))
  68. X
  69. X(ndefstruct (combinable-method-mixin (:class class)))
  70. X
  71. X(ndefstruct (basic-method
  72. X          (:class class)
  73. X          (:include (essential-method))
  74. X          (:constructor make-method-1)
  75. X          (:conc-name method-))
  76. X  (function nil)
  77. X  (discriminator nil)
  78. X  (type-specifiers ())
  79. X  (arglist ())
  80. X  (options () :allocation :dynamic))
  81. X
  82. X(ndefstruct (method (:class class)
  83. X            (:include (combinable-method-mixin
  84. X                   basic-method))))
  85. X
  86. X
  87. X(ndefstruct (essential-discriminator
  88. X          (:class class)
  89. X          (:conc-name discriminator-))
  90. X  (name nil)
  91. X  (methods ())
  92. X  (discriminating-function ())
  93. X  (classical-method-table nil :allocation :dynamic)
  94. X  (cache ()))
  95. X
  96. X(ndefstruct (method-combination-mixin (:class class)
  97. X                      (:conc-name nil))
  98. X  (method-combination-type :daemon)
  99. X  (method-combination-parameters ())
  100. X  (methods-combine-p ())
  101. X  )
  102. X
  103. X(ndefstruct (basic-discriminator
  104. X          (:class class)
  105. X          (:include (essential-discriminator))
  106. X          (:constructor make-discriminator-1)
  107. X          (:conc-name discriminator-))
  108. X
  109. X  (dispatch-order :default)  
  110. X  (inactive-methods () :allocation :dynamic))
  111. X
  112. X(ndefstruct (discriminator (:class class)
  113. X               (:include (method-combination-mixin
  114. X                      basic-discriminator)))
  115. X  )
  116. X
  117. X;;;
  118. X;;; This is really just for bootstrapping, of course this isn't all
  119. X;;; worked out yet.  But this SHOULD really just be for bootstrapping.
  120. X;;; 
  121. X(defmeth method-causes-combination-p ((method basic-method))
  122. X  (ignore method)
  123. X  ())
  124. X
  125. X  ;;   
  126. X;;;;;; 
  127. X  ;;   
  128. X
  129. X
  130. X(defun real-expand-defmeth (name&options arglist body)
  131. X  (unless (listp name&options) (setq name&options (list name&options)))
  132. X  (keyword-parse ((discriminator-class 'discriminator)
  133. X                  (method-class 'method))
  134. X                 (cdr name&options)
  135. X    (dolist (x '(:discriminator-class :method-class))
  136. X      (delete x name&options :test #'(lambda (x y)
  137. X                       (and (listp y) (eq (car y) x)))))
  138. X    (let ((discriminator-class-object (class-named discriminator-class t))
  139. X          (method-class-object (class-named method-class t)))
  140. X      (or discriminator-class-object        ;
  141. X          (error
  142. X        "The :DISCRIMINATOR-CLASS option to defmeth was used to specify~
  143. X             that the class~%of the discriminator should be ~S;~%~
  144. X             but there is no class named ~S."
  145. X        discriminator-class
  146. X        discriminator-class))
  147. X      (or method-class-object
  148. X          (error "The :METHOD-CLASS option to defmeth was used to specify~%~
  149. X                  that the class of the method should be ~S;~%~
  150. X                  but there is no class named ~S."
  151. X                 method-class
  152. X                 method-class))
  153. X      (expand-defmeth-internal (class-prototype discriminator-class-object)
  154. X                   (class-prototype method-class-object)
  155. X                   name&options
  156. X                   arglist
  157. X                   body))))
  158. X
  159. X(defvar *method-being-defined*)
  160. X
  161. X(defmeth expand-defmeth-internal ((proto-discriminator basic-discriminator)
  162. X                  (proto-method basic-method)
  163. X                  name&options arglist body)
  164. X  (keyword-parse ((setf () setf-specified-p))
  165. X                 (cdr name&options)
  166. X    (let* ((discriminator-class-name (class-name
  167. X                       (class-of proto-discriminator)))
  168. X           (method-class-name (class-name (class-of proto-method)))
  169. X           (name (car name&options))
  170. X           (merged-arglist (cons (car arglist) (append setf (cdr arglist))))
  171. X           (merged-args (arglist-without-type-specifiers proto-discriminator
  172. X                                                         proto-method
  173. X                                                         merged-arglist))
  174. X           (merged-type-specifiers
  175. X         (defmethod-argument-specializers arglist))
  176. X           discriminator-name
  177. X           method-name
  178. X       (defmethod-uid (gensym))
  179. X       (load-method-1 ())
  180. X       (documentation ())
  181. X       (declarations ()))
  182. X      (if setf-specified-p
  183. X      (setq discriminator-name (make-setf-discriminator-name name)
  184. X        method-name (make-setf-method-name name
  185. X                           (arglist-type-specifiers
  186. X                             proto-discriminator
  187. X                             proto-method
  188. X                             setf)
  189. X                           merged-type-specifiers))
  190. X      (setq discriminator-name name
  191. X        method-name (make-method-name name
  192. X                          merged-type-specifiers)))
  193. X      (multiple-value-setq (documentation declarations body)
  194. X    (extract-declarations body))
  195. X      (setq load-method-1 `(,discriminator-class-name
  196. X                ,method-class-name
  197. X                ,discriminator-name
  198. X                ,merged-type-specifiers
  199. X                ,merged-args
  200. X                ,(cdr name&options)))
  201. X      ;;
  202. X      ;; There are 4 cases:
  203. X      ;;   - evaluated
  204. X      ;;   - compiled to core
  205. X      ;;   - compiled to file
  206. X      ;;   - loading the compiled file
  207. X      ;;
  208. X      ;; When loading a method which has a run-super in it, there is no way
  209. X      ;; to know which of two events will happen first:
  210. X      ;;   1. the load-time-eval form in the run super will be
  211. X      ;;      evaluated first, or
  212. X      ;;   2. the function to install the loaded method (defmethod-uid)
  213. X      ;;      will be evaluated first.
  214. X      ;; consequently, both the special function (defmethod-uid) and the
  215. X      ;; expansion of run-super must check to see if the other has already
  216. X      ;; run and set the value of defmethod-uid to the method involved.
  217. X      ;; This is what causes the boundp checks of defmethod-uid each time
  218. X      ;; before it is set.
  219. X      ;; 
  220. X      `(progn
  221. X     
  222. X     (eval-when (eval load)
  223. X       
  224. X       (defun ,defmethod-uid ()
  225. X         (declare (special ,defmethod-uid))
  226. X         (unless (boundp ',defmethod-uid)
  227. X           (setq ,defmethod-uid (apply #'load-method-1
  228. X                       ',load-method-1)))
  229. X         ,@(and *real-methods-exist-p*
  230. X            `((record-definition
  231. X            ',discriminator-name 'method
  232. X            ',merged-type-specifiers ',(cdr name&options))
  233. X              (setf (symbol-function ',method-name)
  234. X                #'(lambda ,merged-args
  235. X                ,@documentation
  236. X                ,@declarations
  237. X                (declare (method-function-name ,method-name))
  238. X                ,(wrap-method-body
  239. X                   proto-discriminator
  240. X                   (apply 'compile-method-1 load-method-1)
  241. X                   discriminator-name
  242. X                   defmethod-uid
  243. X                   load-method-1
  244. X                   body)
  245. X                ))))
  246. X         
  247. X         (setf (method-function ,defmethod-uid)
  248. X           (symbol-function ',method-name))
  249. X         
  250. X         (add-method (discriminator-named ',discriminator-name)
  251. X             ,defmethod-uid
  252. X             ()))
  253. X       
  254. X       (,defmethod-uid))
  255. X     
  256. X     (eval-when (compile load eval)
  257. X       
  258. X       ,@(and setf-specified-p
  259. X          `((record-definition
  260. X              ',name 'defsetf ',discriminator-name 'defmeth)
  261. X            (defsetf ,name
  262. X                 ,(arglist-without-type-specifiers
  263. X                proto-discriminator proto-method arglist)
  264. X                 ,(arglist-without-type-specifiers
  265. X                proto-discriminator proto-method setf)
  266. X              (list ',discriminator-name ,@(arglist-args
  267. X                             proto-discriminator
  268. X                             proto-method
  269. X                             merged-args)))))
  270. X       
  271. X       ',discriminator-name)))))
  272. X
  273. X(defmethod wrap-method-body ((mex-generic-function discriminator)
  274. X                 (mex-method method)
  275. X                 generic-function-name
  276. X                 method-uid
  277. X                 load-method-1-args
  278. X                 body)
  279. X  (let ((macroexpand-time-information (list mex-generic-function
  280. X                        mex-method
  281. X                        generic-function-name
  282. X                        method-uid
  283. X                        load-method-1-args)))
  284. X    `(macrolet ,(iterate (((name arglist params fn) in *method-body-macros*))
  285. X          (collect `(,name ,arglist
  286. X                   (funcall (function ,fn)
  287. X                    ',macroexpand-time-information
  288. X                    ,@params))))
  289. X       (block ,generic-function-name
  290. X     . ,body))))
  291. X
  292. X(defun macroexpand-time-generic-function (mti) (nth 0 mti))
  293. X
  294. X(defun macroexpand-time-method (mti) (nth 1 mti))
  295. X
  296. X(defun macroexpand-time-generic-function-name (mti) (nth 2 mti))
  297. X
  298. X(defun macroexpand-time-method-uid (mti) (nth 3 mti))
  299. X
  300. X(defun macroexpand-time-load-method-1-args (mti) (nth 4 mti))
  301. X
  302. X
  303. X(defun load-method-1 (discriminator-class-name
  304. X               method-class-name
  305. X               discriminator-name
  306. X               method-type-specifiers
  307. X              method-arglist
  308. X              options)
  309. X  (let* ((discriminator
  310. X       (ensure-selector-specializable
  311. X         (class-prototype (class-named discriminator-class-name))
  312. X         discriminator-name
  313. X         method-arglist))
  314. X     (method
  315. X       (or (find-method discriminator method-type-specifiers options t)
  316. X           (make method-class-name))))
  317. X    (setf (method-arglist method) method-arglist)
  318. X    (setf (method-type-specifiers method)
  319. X      (parse-type-specifiers
  320. X        discriminator method method-type-specifiers))
  321. X    (setf (method-options method) options)
  322. X    method))
  323. X
  324. X(defun compile-method-1 (discriminator-class-name
  325. X             method-class-name
  326. X             discriminator-name
  327. X             method-type-specifiers
  328. X             method-arglist
  329. X             options)
  330. X  (ignore discriminator-name)
  331. X  (let ((method (make method-class-name)))
  332. X    (setf (method-arglist method) method-arglist)
  333. X    (setf (method-type-specifiers method)
  334. X          (parse-type-specifiers
  335. X        (class-prototype (class-named discriminator-class-name))
  336. X        method
  337. X        method-type-specifiers))
  338. X    (setf (method-options method) options)
  339. X    method))
  340. X
  341. X
  342. X
  343. X(defmeth add-named-method ((proto-discriminator essential-discriminator)
  344. X               (proto-method essential-method)
  345. X               discriminator-name
  346. X               arglist
  347. X               type-specs
  348. X               extra
  349. X               function)
  350. X  ;; What about changing the class of the discriminator if there is
  351. X  ;; one.  Whose job is that anyways.  Do we need something kind of
  352. X  ;; like class-for-redefinition?
  353. X  (let* ((discriminator
  354. X       ;; Modulo bootstrapping hair, this is just:
  355. X       ;;   (or (discriminator-named ..)
  356. X       ;;       (make-specializable))
  357. X       (ensure-selector-specializable proto-discriminator
  358. X                      discriminator-name
  359. X                      arglist))
  360. X     (existing (find-method discriminator type-specs extra t))
  361. X     (method (or existing
  362. X             (make (class-of proto-method)))))
  363. X    (when existing (change-class method (class-of proto-method)))
  364. X    (setf (method-arglist method) arglist)
  365. X    (setf (method-function method) function)
  366. X    (setf (method-type-specifiers method) type-specs)
  367. X    (add-method discriminator method extra)))
  368. X
  369. X(defmeth add-method ((discriminator essential-discriminator)
  370. X             (method essential-method)
  371. X             extra)
  372. X  (ignore extra)
  373. X  (let ((type-specs (method-type-specifiers method))
  374. X       ;(options (method-options method))
  375. X       ;(methods (discriminator-methods discriminator))
  376. X    )
  377. X    (setf (method-discriminator method) discriminator)
  378. X;    ;; Put the new method where it belongs, either:
  379. X;    ;;  - The same (EQ) method object is already on discriminator-methods
  380. X;    ;;    of the discriminator so we don't need to do anything to put the
  381. X;    ;;    new methods where it belongs.
  382. X;    ;;  - There is an method on discriminator-methods which is equal to
  383. X;    ;;    the new method (according to METHOD-EQUAL).  In this case, we
  384. X;    ;;    replace the existing method with the new one.
  385. X;    ;;  - We just add the new method to discriminator-methods by pushing
  386. X;    ;;    it onto that list.
  387. X;    (unless (memq method methods)
  388. X;      (do* ((tail (discriminator-methods discriminator) (cdr tail))
  389. X;        (existing-method (car tail) (car tail)))
  390. X;       ((cond ((null existing-method)         
  391. X;           (push method (discriminator-methods discriminator)))
  392. X;          ((method-equal existing-method type-specs options)
  393. X;           (remove-method discriminator existing-method)
  394. X;           (return (add-method discriminator method))))
  395. X;        
  396. X;        (when (method-causes-combination-p method)             ;NOT part of
  397. X;          (pushnew method (methods-combine-p discriminator)));standard
  398. X;                                         ;protocol.
  399. X;        (dolist (argument-specifier type-specs)
  400. X;          (add-method-on-argument-specifier discriminator
  401. X;                        method
  402. X;                        argument-specifier)))
  403. X;    ()))
  404. X    (pushnew method (discriminator-methods discriminator))
  405. X    (dolist (argument-specifier type-specs)
  406. X      (add-method-on-argument-specifier discriminator
  407. X                    method
  408. X                    argument-specifier)))
  409. X    (discriminator-changed discriminator method t)
  410. X    (update-pretty-arglist discriminator method)    ;NOT part of
  411. X                                ;standard protocol.
  412. X    ())
  413. X
  414. X
  415. X(defmeth remove-named-method (discriminator-name
  416. X                  argument-specifiers
  417. X                  &optional extra)
  418. X  (let ((discriminator ())
  419. X    (method ()))
  420. X    (cond ((null (setq discriminator (discriminator-named
  421. X                       discriminator-name)))
  422. X       (error "There is no discriminator named ~S." discriminator-name))
  423. X      ((null (setq method (find-method discriminator
  424. X                       argument-specifiers 
  425. X                       extra
  426. X                       t)))
  427. X       (error "There is no method for the discriminator ~S~%~
  428. X                   which matches the argument-specifiers ~S."
  429. X          discriminator
  430. X          argument-specifiers))
  431. X      (t
  432. X       (remove-method discriminator method)))))
  433. X
  434. X(defmeth remove-method ((discriminator basic-discriminator) method)
  435. X  (setf (method-discriminator method) nil)
  436. X  (setf (discriminator-methods discriminator)
  437. X    (delq method (discriminator-methods discriminator)))
  438. X  (dolist (type-spec (method-type-specifiers method))
  439. X    (remove-method-on-argument-specifier discriminator method type-spec))
  440. X  (discriminator-changed discriminator method nil)
  441. X  discriminator)
  442. X
  443. X
  444. X
  445. X(defmeth add-method-on-argument-specifier
  446. X     ((discriminator essential-discriminator)
  447. X      (method essential-method)
  448. X      argument-specifier)
  449. X  (ignore method)
  450. X  (when (classp argument-specifier)
  451. X    (pushnew method
  452. X         (class-direct-methods argument-specifier))
  453. X    ;; This is a bug.  This needs to be split up into a method on
  454. X    ;; essential class and a method on class or something.
  455. X    (when (methods-combine-p discriminator)
  456. X      (pushnew discriminator
  457. X           (class-discriminators-which-combine-methods
  458. X         argument-specifier)))))
  459. X
  460. X(defmeth remove-method-on-argument-specifier
  461. X     ((discriminator essential-discriminator)
  462. X      (method essential-method)
  463. X      argument-specifier)
  464. X  (ignore method)
  465. X  (when (classp argument-specifier)
  466. X    (setf (class-direct-methods argument-specifier)
  467. X      (delq method
  468. X        (class-direct-methods argument-specifier)))
  469. X    (when (methods-combine-p discriminator)
  470. X      (setf (class-discriminators-which-combine-methods
  471. X          argument-specifier)
  472. X        (delq discriminator
  473. X          (class-discriminators-which-combine-methods
  474. X            argument-specifier))))))
  475. X
  476. X
  477. X(defun make-specializable (function-name &rest options)
  478. X  (when options (setq options (list* ':allow-other-keys t options)))
  479. X  (keyword-bind ((arglist nil arglist-specified-p)
  480. X         (discriminator-class 'discriminator)
  481. X         (dispatch nil dispatch-p))
  482. X        options
  483. X    (cond ((not (null arglist-specified-p)))
  484. X      ((fboundp 'function-arglist)
  485. X       ;; function-arglist exists, get the arglist from it.
  486. X       ;; Note: the funcall of 'function-arglist prevents
  487. X       ;;       compiler warnings at least in some lisps.
  488. X       (setq arglist (funcall 'function-arglist function-name)))
  489. X      ((fboundp function-name)
  490. X       (error
  491. X         "The :arglist argument to make-specializable was not supplied~%~
  492. X              and there is no version of FUNCTION-ARGLIST defined for this~%~
  493. X              port of Portable CommonLoops.~%~
  494. X              You must either define a version of FUNCTION-ARGLIST (which~%~
  495. X              should be easy), and send it off to the Portable CommonLoops~%~
  496. X              people or you should call make-specializable again with the~%~
  497. X              function's arglist as its second argument.")))
  498. X    (setq dispatch
  499. X      (if dispatch-p
  500. X          (iterate ((disp in dispatch))
  501. X        (unless (memq disp arglist)
  502. X          (error "There is a symbol in the :dispatch argument (~S)~%~
  503. X                          which isn't in the arglist."))
  504. X        (collect (position disp arglist)))
  505. X          :default))
  506. X    (let ((discriminator-class-object
  507. X        (if (classp discriminator-class)
  508. X        discriminator-class
  509. X        (class-named discriminator-class t)))
  510. X      (discriminator nil))
  511. X      (if (null discriminator-class-object)
  512. X      (error
  513. X        "The :DISCRIMINATOR-CLASS argument to make-specializable is ~S~%~
  514. X             but there is no class by that name."
  515. X        discriminator-class)
  516. X      (setq discriminator             
  517. X        (apply #'make discriminator-class-object
  518. X               :name function-name
  519. X               :dispatch-order dispatch
  520. X               options)))
  521. X;     (setf (function-pretty-arglist function-name) arglist)
  522. X      (if arglist-specified-p
  523. X      (put-slot-always discriminator 'pretty-arglist arglist)
  524. X      (remove-dynamic-slot discriminator 'pretty-arglist))
  525. X      (setf (discriminator-named function-name) discriminator)
  526. X      (when (fboundp function-name)
  527. X    (add-named-method (class-prototype (class-named 'discriminator))
  528. X              (class-prototype (class-named 'method))
  529. X              function-name
  530. X              arglist
  531. X              ()
  532. X              ()
  533. X              (symbol-function function-name)))
  534. X      discriminator)))
  535. X
  536. X
  537. X
  538. X
  539. X
  540. X(defun update-pretty-arglist (discriminator method)
  541. X  (setf (function-pretty-arglist
  542. X      (or (discriminator-name discriminator)
  543. X          (discriminator-discriminating-function discriminator)))
  544. X    (or (get-slot-using-class (class-of discriminator) discriminator
  545. X                  'pretty-arglist t ())
  546. X        (method-arglist method))))
  547. X
  548. X(defmeth discriminator-pretty-arglist ((discriminator basic-discriminator))
  549. X  (or (get-slot-using-class (class-of discriminator) discriminator
  550. X                'pretty-arglist t ())
  551. X      (let ((method (or (discriminator-default-method discriminator)
  552. X            (car (discriminator-methods discriminator)))))
  553. X    (and method (method-arglist method)))))
  554. X
  555. X(defmeth ensure-selector-specializable ((proto-discriminator
  556. X                       essential-discriminator)
  557. X                     selector arglist)
  558. X  (let ((discriminator (discriminator-named selector)))
  559. X    (cond ((not (null discriminator)) discriminator)
  560. X          ((or (not (fboundp selector))
  561. X               (eq *error-when-defining-method-on-existing-function*
  562. X           'bootstrapping))
  563. X           (setf (discriminator-named selector)
  564. X                 (make (class-of proto-discriminator) :name selector)))
  565. X          ((null *error-when-defining-method-on-existing-function*)
  566. X           (make-specializable selector
  567. X                   :arglist arglist
  568. X                   :discriminator-class (class-of
  569. X                              proto-discriminator))
  570. X           (discriminator-named selector))
  571. X          (t
  572. X           (error "Attempt to add a method to the lisp function ~S without~%~
  573. X                   first calling make-specializable.  Before attempting to~
  574. X                   define a method on ~S~% you should evaluate the form:~%~
  575. X                   (~S '~S)"
  576. X                  selector selector 'make-specializable selector)))))
  577. X
  578. X(defmeth find-method (discriminator type-specifiers options &optional parse)
  579. X  (iterate ((method in (discriminator-methods discriminator)))
  580. X    (when (method-equal method
  581. X            (if parse
  582. X                (parse-type-specifiers discriminator
  583. X                           method
  584. X                           type-specifiers)
  585. X                type-specifiers)
  586. X            options)
  587. X      (return method))))
  588. X
  589. X(defmeth method-equal ((method basic-method) argument-specifiers options)
  590. X  (and (equal options (method-options method))
  591. X       (equal argument-specifiers (method-type-specifiers method))))
  592. X
  593. X
  594. X(defmeth discriminator-default-method ((discriminator essential-discriminator))
  595. X  (find-method discriminator () ()))
  596. X
  597. X(defmeth install-discriminating-function ((discriminator
  598. X                        essential-discriminator)
  599. X                      where
  600. X                      function
  601. X                      &optional inhibit-compile-p)
  602. X  (ignore discriminator)
  603. X  (check-type where symbol "a symbol other than NIL")
  604. X  (check-type function function "a funcallable object")
  605. X  
  606. X  (when (and (listp function)
  607. X         (eq (car function) 'lambda)
  608. X         (null inhibit-compile-p))
  609. X    (setq function (compile nil function)))
  610. X
  611. X  (if where
  612. X      (setf (symbol-function where) function)
  613. X      (setf (discriminator-discriminating-function discriminator) function)))
  614. X
  615. X
  616. X  ;;   
  617. X;;;;;; Discriminator-Based caching.
  618. X  ;;
  619. X;;; Methods are cached in a discriminator-based cache.  The cache is an N-key
  620. X;;; cache based on the number of specialized arguments the discriminator has.
  621. X;;; As yet the size of the cache does not change statically or dynamically.
  622. X;;; Because of this I allow myself the freedom of computing the mask at
  623. X;;; compile time and not even storing it in the discriminator.
  624. X
  625. X(defvar *default-discriminator-cache-size* 8)
  626. X
  627. X(defun make-discriminator-cache (&optional
  628. X                  (size *default-discriminator-cache-size*))
  629. X  (make-memory-block size))
  630. X
  631. X(defun make-discriminator-cache-mask (discriminator-cache
  632. X                      no-of-specialized-args)
  633. X  (make-memory-block-mask (memory-block-size discriminator-cache)
  634. X                          (+ no-of-specialized-args 1)))
  635. X
  636. X(defmeth flush-discriminator-caches ((discriminator essential-discriminator))
  637. X  (let ((cache (discriminator-cache discriminator)))
  638. X    (when cache (clear-memory-block (discriminator-cache discriminator) 0))))
  639. X
  640. X(defmeth initialize-discriminator-cache ((self essential-discriminator)
  641. X                                            no-of-specialized-args)
  642. X  (ignore no-of-specialized-args)
  643. X  (unless (discriminator-cache self)
  644. X    (setf (discriminator-cache self) (make-discriminator-cache))))
  645. X
  646. X(defmacro discriminator-cache-offset (mask &rest classes)
  647. X  `(logand ,mask
  648. X           ,@(iterate ((class in classes))
  649. X           (collect `(object-cache-no ,class ,mask)))))
  650. X
  651. X(defmacro discriminator-cache-entry (cache offset offset-from-offset)
  652. X  `(memory-block-ref ,cache (+ ,offset ,offset-from-offset)))
  653. X
  654. X(defmacro cache-method (cache mask method-function &rest classes)
  655. X  `(let* ((.offset. (discriminator-cache-offset ,mask ,@classes)))
  656. X     ;; Once again, we have to endure a little brain damage because we can't
  657. X     ;; count on having without-interrupts.  I suppose the speed loss isn't
  658. X     ;; too significant since this is only when we get a cache miss.
  659. X     (setf (discriminator-cache-entry ,cache .offset. 0) nil)
  660. X     ,@(iterate ((class in (cdr classes)) (key-no from 1))
  661. X         (collect `(setf (discriminator-cache-entry ,cache .offset. ,key-no)
  662. X             ,class)))
  663. X     (prog1
  664. X       (setf (discriminator-cache-entry ,cache .offset. ,(length classes))
  665. X         ,method-function)
  666. X       (setf (discriminator-cache-entry ,cache .offset. 0) ,(car classes)))))
  667. X
  668. X(defmacro cached-method (var cache mask &rest classes)
  669. X  `(let ((.offset. (discriminator-cache-offset ,mask . ,classes)))
  670. X     (and ,@(iterate ((class in classes) (key-no from 0))
  671. X              (collect
  672. X                `(eq (discriminator-cache-entry ,cache .offset. ,key-no)
  673. X             ,class)))
  674. X          (setq ,var (discriminator-cache-entry ,cache
  675. X                        .offset.
  676. X                        ,(length classes)))
  677. X          t)))
  678. X
  679. X(defmeth make-caching-discriminating-function (discriminator lookup-function
  680. X                                  cache
  681. X                                  mask)
  682. X  (multiple-value-bind (required restp specialized-positions)
  683. X      (compute-discriminating-function-arglist-info discriminator)
  684. X    (funcall (get-templated-function-constructor
  685. X           'caching-discriminating-function
  686. X           required
  687. X           restp
  688. X           specialized-positions
  689. X           lookup-function)
  690. X             discriminator cache mask)))
  691. X
  692. X(defun make-checking-discriminating-function (discriminator method-function
  693. X                                                            type-specs
  694. X                                default-function)
  695. X  (multiple-value-bind (required restp)
  696. X      (compute-discriminating-function-arglist-info discriminator)
  697. X    (let ((check-positions
  698. X        (iterate ((type-spec in type-specs)
  699. X              (pos from 0))
  700. X          (collect (and (neq type-spec 't) pos)))))
  701. X      (apply (get-templated-function-constructor
  702. X           'checking-discriminating-function
  703. X           required
  704. X           restp
  705. X           (if default-function t nil)
  706. X           check-positions)
  707. X             discriminator method-function default-function type-specs))))
  708. X
  709. X
  710. X  ;;   
  711. X;;;;;; 
  712. X  ;;   
  713. X
  714. X(defvar *always-remake-discriminating-function* nil)
  715. X
  716. X(defmeth make-discriminating-function ((discriminator
  717. X                     essential-discriminator))
  718. X  (let ((default (discriminator-default-method discriminator))
  719. X        (methods (discriminator-methods discriminator)))
  720. X    (cond ((null methods)
  721. X       (make-no-methods-discriminating-function discriminator))
  722. X      ((and default (null (cdr methods)))
  723. X           (make-default-method-only-discriminating-function discriminator))
  724. X          ((or (and default (null (cddr methods)))
  725. X           (and (null default) (null (cdr methods))))
  726. X           (make-single-method-only-discriminating-function discriminator))
  727. X          ((every #'(lambda (m)
  728. X                      (classical-type-specifiers-p
  729. X            (method-type-specifiers m)))
  730. X                  methods)
  731. X           (make-classical-methods-only-discriminating-function
  732. X         discriminator))
  733. X          (t
  734. X           (make-multi-method-discriminating-function discriminator)))))
  735. X
  736. X(defmeth make-no-methods-discriminating-function (discriminator)
  737. X  (instaar *always-remake-discriminating-function* nil)
  738. X (discriminator-name discriminator)
  739. X    #'(lambda (&rest ignore)
  740. X    (error "There are no methods on the discriminator ~S,~%~
  741. X                so it is an error to call it."
  742. X           discriminator))))
  743. X
  744. X(defmeth make-default-method-only-discriminating-function
  745. X     ((self essential-discriminator))
  746. X  (install-discriminating-function
  747. X    self
  748. X    (discriminator-name self)
  749. X    (method-function (discriminator-default-method self))))
  750. X
  751. X(defmeth make-single-method-only-discriminating-function
  752. X      ((self essential-discriminator))
  753. X  (let* ((methods (discriminator-methods self))
  754. X     (default (discriminator-default-method self))
  755. X     (method (if (eq (car methods) default)
  756. X             (cadr methods)
  757. X             (car methods)))
  758. X         (method-type-specifiers (method-type-specifiers method))
  759. X         (method-function (method-function method)))
  760. X    (install-discriminating-function
  761. X      self
  762. X      (discriminator-name self)
  763. X      (make-checking-discriminating-function
  764. X    self
  765. X    method-function
  766. X    method-type-specifiers
  767. X    (and default (method-function default))))))
  768. X
  769. X(defmeth make-classical-methods-only-discriminating-function
  770. X      ((self essential-discriminator))
  771. X  (initialize-discriminator-cache self 1)
  772. X  (let ((default-method (discriminator-default-method self))
  773. X    (methods (discriminator-methods self)))
  774. X    (setf (discriminator-classical-method-table self)
  775. X      (cons (and default-method (method-function default-method))
  776. X        (iterate ((method in methods))
  777. X          (unless (eq method default-method)
  778. X            (collect (cons (car (method-type-specifiers method))
  779. X                   (method-function method))))))))
  780. X  (let* ((cache (discriminator-cache self))
  781. X     (mask (make-discriminator-cache-mask cache 1)))
  782. X    (install-discriminating-function
  783. X      self
  784. X      (discriminator-name self)
  785. X      (make-caching-discriminating-function
  786. X    self 'lookup-classical-method cache mask))))
  787. X
  788. X(defun lookup-classical-method (discriminator class)
  789. X  ;; There really should be some sort of more sophisticated protocol going
  790. X  ;; on here.  Compare type-specifiers and all that.
  791. X  (let* ((classical-method-table
  792. X       (get-slot--class discriminator 'classical-method-table)))
  793. X    (or (iterate ((super in (get-slot--class class 'class-precedence-list)))
  794. X          (let ((hit (assq super (cdr classical-method-table))))
  795. X            (when hit (return (cdr hit)))))
  796. X    (car classical-method-table))))
  797. X
  798. X(defmeth make-multi-method-discriminating-function
  799. X      ((self essential-discriminator))
  800. X  (multiple-value-bind (required restp specialized)
  801. X      (compute-discriminating-function-arglist-info self)
  802. X    (ignore required restp)
  803. X    (initialize-discriminator-cache self (length specialized))
  804. X    (let* ((cache (discriminator-cache self))
  805. X       (mask (make-discriminator-cache-mask cache (length specialized))))
  806. X      (install-discriminating-function
  807. X    self
  808. X    (discriminator-name self)
  809. X    (make-caching-discriminating-function
  810. X      self 'lookup-multi-method cache mask)))))
  811. X
  812. X(defvar *lookup-multi-method-internal*
  813. X    (make-array (min 256. call-arguments-limit)))
  814. X
  815. X(defun lookup-multi-method-internal (discriminator classes)
  816. X  (let* ((methods (discriminator-methods discriminator))
  817. X     (cpls *lookup-multi-method-internal*)
  818. X     (order (get-slot--class discriminator 'dispatch-order))
  819. X         (most-specific-method nil)
  820. X         (most-specific-type-specs ())
  821. X     (type-specs ()))
  822. X    ;; Put all the class-precedence-lists in a place where we can save
  823. X    ;; them as we look through all the methods.
  824. X    (without-interrupts
  825. X      (iterate ((class in classes)
  826. X        (i from 0))
  827. X    (setf (svref cpls i) (get-slot--class class 'class-precedence-list)))
  828. X      (dolist (method methods)
  829. X    (setq type-specs (get-slot--class method 'type-specifiers))
  830. X    (when (iterate ((type-spec in  type-specs)
  831. X            (i from 0))
  832. X        (or (eq type-spec 't)
  833. X            (memq type-spec (svref cpls i))
  834. X            (return nil))
  835. X        (finally (return t)))
  836. X      (if (null most-specific-method)
  837. X          (setq most-specific-method method
  838. X            most-specific-type-specs type-specs)
  839. X          (case (compare-type-specifier-lists
  840. X              most-specific-type-specs type-specs nil
  841. X              () classes order)
  842. X        (2 (setq most-specific-method method
  843. X             most-specific-type-specs type-specs))
  844. X        (1))))))
  845. X    (or most-specific-method
  846. X    (discriminator-default-method discriminator))))
  847. X
  848. X(defun lookup-multi-method (discriminator &rest classes)
  849. X  (declare (inline lookup-multi-method-internal))
  850. X  (let ((method (lookup-multi-method-internal discriminator classes)))
  851. X    (and method (method-function method))))
  852. X
  853. X(defun lookup-method (discriminator &rest classes)
  854. X  (declare (inline lookup-multi-method-internal))
  855. X  (lookup-multi-method-internal discriminator classes))
  856. X
  857. X  ;;   
  858. X;;;;;; Code for parsing arglists (in the usual case).
  859. X  ;;   (when discriminator is class DISCRIMINATOR and method is class METHOD)
  860. X;;;
  861. X;;; arglist-type-specifiers
  862. X;;; Given an arglist this returns its type-specifiers.  Trailing T's (both
  863. X;;; implicit and explicit) are dropped.  The type specifiers are returned as
  864. X;;; they are found in the arglist, they are not parsed into internal
  865. X;;; type-specs.
  866. X;;;
  867. X(defmeth arglist-type-specifiers ((proto-disc basic-discriminator)
  868. X                  (proto-meth basic-method)
  869. X                  arglist)
  870. X  (let ((arg (car arglist)))
  871. X    (and arglist
  872. X         (not (memq arg '(&optional &rest &key &aux)))  ;Don't allow any
  873. X                                                        ;type-specifiers
  874. X                                                    ;after one of these.
  875. X         (let ((tail (arglist-type-specifiers proto-disc
  876. X                          proto-meth
  877. X                          (cdr arglist)))
  878. X               (type-spec (and (listp arg) (cadr arg))))
  879. X           (or (and tail (cons (or type-spec 't) tail))
  880. X               (and type-spec (cons type-spec ())))))))
  881. X
  882. X;;; arglist-without-type-specifiers
  883. X;;; Given an arglist remove the type specifiers.
  884. X;;; 
  885. X(defmeth arglist-without-type-specifiers ((proto-disc basic-discriminator)
  886. X                      (proto-meth basic-method)
  887. X                      arglist)
  888. X  (let ((arg (car arglist)))
  889. X    (and arglist
  890. X         (if (memq arg '(&optional &rest &key &aux))    ;don't allow any
  891. X                                                        ;type-specifiers
  892. X                                                        ;after one of these.
  893. X             arglist
  894. X             (cons (if (listp arg) (car arg) arg)
  895. X                   (arglist-without-type-specifiers proto-disc
  896. X                            proto-meth
  897. X                            (cdr arglist)))))))
  898. X
  899. X(defmeth arglist-args ((discriminator-class basic-discriminator)
  900. X               (method-class basic-method)
  901. X               arglist)
  902. X  (and arglist
  903. X       (cond ((eq (car arglist) '&aux) ())
  904. X             ((memq (car arglist) '(&optional &rest &key))
  905. X              (arglist-args discriminator-class method-class (cdr arglist)))
  906. X             (t
  907. X              ;; This plays on the fact that no type specifiers are allowed
  908. X          ;; on arguments that can have default values.
  909. X              (cons (if (listp (car arglist)) (caar arglist) (car arglist))
  910. X                    (arglist-args discriminator-class
  911. X                  method-class
  912. X                  (cdr arglist)))))))
  913. X
  914. X(defmeth parse-type-specifiers ((proto-discriminator basic-discriminator)
  915. X                (proto-method basic-method)
  916. X                type-specifiers)
  917. X  (iterate ((type-specifier in type-specifiers))
  918. X    (collect (parse-type-specifier proto-discriminator
  919. X                   proto-method
  920. X                   type-specifier))))
  921. X
  922. X(defmeth parse-type-specifier ((proto-discriminator basic-discriminator)
  923. X                                (proto-method basic-method)
  924. X                                type-specifier)
  925. X  (ignore proto-discriminator proto-method)
  926. X  (cond ((eq type-specifier 't) 't)
  927. X        ((symbolp type-specifier)
  928. X         (or (class-named type-specifier nil)
  929. X             (error
  930. X           "~S used as a type-specifier, but is not the name of a class."
  931. X           type-specifier)))
  932. X        ((classp type-specifier) type-specifier)
  933. X        (t (error "~S is not a legal type-specifier." type-specifier))))
  934. X
  935. X(defmeth unparse-type-specifiers ((method essential-method))
  936. X  (iterate ((parsed-type-spec in (method-type-specifiers method)))
  937. X    (collect (unparse-type-specifier method parsed-type-spec))))
  938. X
  939. X(defmeth unparse-type-specifier ((method essential-method) type-spec)
  940. X  (ignore method)
  941. X  (if (classp type-spec)
  942. X      (class-name type-spec)
  943. X      type-spec))
  944. X
  945. X(defun classical-type-specifiers-p (typespecs)
  946. X  (or (null typespecs)
  947. X      (and (classp (car typespecs))
  948. X           (null (cdr typespecs)))))
  949. X
  950. X;;;
  951. X;;; Compute various information about a discriminator's arglist by looking at
  952. X;;; the argument lists of the methods.  The hair for trying not to use &rest
  953. X;;; arguments lives here.
  954. X;;;  The values returned are:
  955. X;;;    number-of-required-arguments
  956. X;;;       the number of required arguments to this discrimator's
  957. X;;;       discriminating function
  958. X;;;    &rest-argument-p
  959. X;;;       whether or not this discriminator's discriminating
  960. X;;;       function takes an &rest argument.
  961. X;;;    specialized-argument-positions
  962. X;;;       a list of the positions of the arguments this discriminator
  963. X;;;       specializes (e.g. for a classical discrimator this is the
  964. X;;;       list: (1)).
  965. X;;;
  966. X;;; As usual, it is legitimate to specialize the -internal function that is
  967. X;;; why I put it there, since I certainly could have written this more
  968. X;;; efficiently if I didn't want to provide that extensibility.
  969. X;;; 
  970. X(defmeth compute-discriminating-function-arglist-info
  971. X     ((discriminator essential-discriminator)
  972. X      &optional (methods () methods-p))
  973. X  (declare (values number-of-required-arguments
  974. X                   &rest-argument-p
  975. X                   specialized-argument-postions))
  976. X  (unless methods-p
  977. X    (setq methods (discriminator-methods discriminator)))
  978. X  (let ((number-required nil)
  979. X        (restp nil)
  980. X        (specialized-positions ()))
  981. X    (iterate ((method in methods))
  982. X      (multiple-value-setq (number-required restp specialized-positions)
  983. X        (compute-discriminating-function-arglist-info-internal
  984. X      discriminator method number-required restp specialized-positions)))
  985. X    (values number-required restp (sort specialized-positions #'<))))
  986. X
  987. X(defmeth compute-discriminating-function-arglist-info-internal
  988. X     ((discriminator essential-discriminator)
  989. X      (method essential-method)
  990. X      number-of-requireds restp specialized-argument-positions)
  991. X  (ignore discriminator)
  992. X  (let ((requireds 0))
  993. X    ;; Go through this methods arguments seeing how many are required,
  994. X    ;; and whether there is an &rest argument.
  995. X    (iterate ((arg in (method-arglist method)))
  996. X      (cond ((eq arg '&aux) (return))
  997. X            ((memq arg '(&optional &rest &key))
  998. X             (return (setq restp t)))
  999. X        ((memq arg lambda-list-keywords))
  1000. X            (t (incf requireds))))
  1001. X    ;; Now go through this method's type specifiers to see which
  1002. X    ;; argument positions are type specified.  Treat T specially
  1003. X    ;; in the usual sort of way.  For efficiency don't bother to
  1004. X    ;; keep specialized-argument-positions sorted, rather depend
  1005. X    ;; on our caller to do that.
  1006. X    (iterate ((type-spec in (method-type-specifiers method))
  1007. X              (pos from 0))
  1008. X      (unless (eq type-spec 't)
  1009. X    (pushnew pos specialized-argument-positions)))
  1010. X    ;; Finally merge the values for this method into the values
  1011. X    ;; for the exisiting methods and return them.  Note that if
  1012. X    ;; num-of-requireds is NIL it means this is the first method
  1013. X    ;; and we depend on that.
  1014. X    (values (min (or number-of-requireds requireds) requireds)
  1015. X            (or restp
  1016. X        (and number-of-requireds (/= number-of-requireds requireds)))
  1017. X            specialized-argument-positions)))
  1018. X
  1019. X(defun make-discriminating-function-arglist (number-required-arguments restp)
  1020. X  (iterate ((i from 0 below number-required-arguments))
  1021. X    (collect (intern (format nil "Discriminating Function Arg ~D" i)))
  1022. X    (finally (when restp
  1023. X               (collect '&rest)
  1024. X               (collect (intern "Discriminating Function &rest Arg"))))))
  1025. X
  1026. X(defmeth compare-methods (discriminator method-1 method-2)
  1027. X  (ignore discriminator)
  1028. X  (let ((compare ()))
  1029. X    (iterate ((ts-1 in (method-type-specifiers method-1))
  1030. X          (ts-2 in (method-type-specifiers method-2)))
  1031. X      (cond ((eq ts-1 ts-2) (setq compare '=))
  1032. X        ((eq ts-1 't)   (setq compare method-2))
  1033. X        ((eq ts-2 't)   (setq compare method-1))        
  1034. X        ((memq ts-1 (class-class-precedence-list ts-2))
  1035. X         (setq compare method-2))
  1036. X        ((memq ts-2 (class-class-precedence-list ts-1))
  1037. X         (setq compare method-1))
  1038. X        (t (return nil)))
  1039. X      (finally (return compare)))))
  1040. X
  1041. X  ;;   
  1042. X;;;;;; Comparing type-specifiers, statically or wrt an object.
  1043. X  ;;
  1044. X;;; compare-type-specifier-lists compares two lists of type specifiers
  1045. X;;; compare-type-specifiers compare two type specifiers
  1046. X;;; If static-p it t the comparison is done statically, otherwise it is
  1047. X;;; done with respect to object(s).  The value returned is:
  1048. X;;;    1    if type-spec-1 is more specific
  1049. X;;;    2    if type-spec-2 is more specific
  1050. X;;;    =    if they are equal
  1051. X;;;    NIL  if they cannot be disambiguated
  1052. X;;;
  1053. X(defun compare-type-specifier-lists (type-spec-list-1
  1054. X                     type-spec-list-2
  1055. X                     staticp
  1056. X                     args
  1057. X                     classes
  1058. X                     order)
  1059. X  (when (or type-spec-list-1 type-spec-list-2)
  1060. X    (ecase (compare-type-specifiers (or (car type-spec-list-1) t)
  1061. X                                    (or (car type-spec-list-2) t)
  1062. X                                    staticp
  1063. X                                    (car args)
  1064. X                                    (car classes))
  1065. X      (1 '1)
  1066. X      (2 '2)
  1067. X      (= (if (eq order :default)
  1068. X         (compare-type-specifier-lists (cdr type-spec-list-1)
  1069. X                       (cdr type-spec-list-2)
  1070. X                       staticp
  1071. X                       (cdr args)
  1072. X                       (cdr classes)
  1073. X                       order)
  1074. X         (compare-type-specifier-lists (nth (car order) type-spec-list-1)
  1075. X                       (nth (car order) type-spec-list-2)
  1076. X                       staticp
  1077. X                       (cdr args)
  1078. X                       (cdr classes)
  1079. X                       (cdr order))))
  1080. X        
  1081. X      (nil
  1082. X        (unless staticp
  1083. X          (error "The type specifiers ~S and ~S can not be disambiguated~
  1084. X                  with respect to the argument: ~S"
  1085. X                 (or (car type-spec-list-1) t)
  1086. X                 (or (car type-spec-list-2) t)
  1087. X                 (car args)
  1088. X                 (car classes)))))))
  1089. X
  1090. X(defun compare-type-specifiers (type-spec-1 type-spec-2 staticp arg class)
  1091. X  (cond ((equal type-spec-1 type-spec-2) '=)
  1092. X        ((eq type-spec-2 t) '1)
  1093. X        ((eq type-spec-1 t) '2)
  1094. X        ((and (classp type-spec-1) (classp type-spec-2))
  1095. X;        (if staticp
  1096. X;            (if (common-subs type-spec-1 type-spec-2)
  1097. X;                nil
  1098. X;                (let ((supers (common-supers type-spec-1 type-spec-2)))
  1099. X;                  (cond ((cdr supers) nil)
  1100. X;                        ((eq (car supers) type-spec-1) '2)
  1101. X;                        ((eq (car supers) type-spec-2) '1)
  1102. X;                        (t 'disjoint))))
  1103. X             (iterate ((super in (class-class-precedence-list (or class (class-of arg)))))
  1104. X               (cond ((eq super type-spec-1)
  1105. X                      (return '1))
  1106. X                     ((eq super type-spec-2)
  1107. X                      (return '2)))))
  1108. X;)
  1109. X        (t
  1110. X         (compare-complex-type-specifiers type-spec-1 type-spec-2 staticp arg class))))
  1111. X
  1112. X(defun compare-complex-type-specifiers (type-spec-1 type-spec-2 static-p arg class)
  1113. X  (ignore type-spec-1 type-spec-2 static-p arg class)
  1114. X  (error "Complex type specifiers are not yet supported."))
  1115. X
  1116. X(defmeth no-matching-method (discriminator)
  1117. X  (let ((class-of-discriminator (class-of discriminator)))
  1118. X    (if (eq (class-of class-of-discriminator) (class-named 'class))
  1119. X        ;; The meta-class of the discriminator is class, we can get at
  1120. X        ;; it's name slot without doing any method lookup.
  1121. X        (let ((name (get-slot--class discriminator 'name)))
  1122. X          (if (and name (symbolp name))
  1123. X              (error "No matching method for: ~S." name)
  1124. X              (error "No matching method for the anonymous discriminator: ~S."
  1125. X                     discriminator)))
  1126. X        (error "No matching method for the discriminator: ~S." discriminator))))
  1127. X  ;;   
  1128. X;;;;;; Optimizing GET-SLOT
  1129. X  ;;   
  1130. X
  1131. X(defmeth method-argument-class ((method basic-method) argument)
  1132. X  (let* ((arglist (method-arglist method))
  1133. X         (position (position argument arglist)))
  1134. X    (and position (nth position (method-type-specifiers method)))))
  1135. X
  1136. X
  1137. X(defmeth optimize-get-slot ((class basic-class)
  1138. X                form)
  1139. X  (declare (ignore class))
  1140. X  (cons 'get-slot--class (cdr form)))
  1141. X
  1142. X(defmeth optimize-setf-of-get-slot ((class basic-class)
  1143. X                    form)
  1144. X  (declare (ignore class))
  1145. X  (cons 'put-slot--class (cdr form)))
  1146. X
  1147. END_OF_FILE
  1148. if test 42046 -ne `wc -c <'methods.l'`; then
  1149.     echo shar: \"'methods.l'\" unpacked with wrong size!
  1150. fi
  1151. # end of 'methods.l'
  1152. fi
  1153. echo shar: End of archive 12 \(of 13\).
  1154. cp /dev/null ark12isdone
  1155. MISSING=""
  1156. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 ; do
  1157.     if test ! -f ark${I}isdone ; then
  1158.     MISSING="${MISSING} ${I}"
  1159.     fi
  1160. done
  1161. if test "${MISSING}" = "" ; then
  1162.     echo You have unpacked all 13 archives.
  1163.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1164. else
  1165.     echo You still need to unpack the following archives:
  1166.     echo "        " ${MISSING}
  1167. fi
  1168. ##  End of shell archive.
  1169. exit 0
  1170. -- 
  1171.  
  1172. Rich $alz            "Anger is an energy"
  1173. Cronus Project, BBN Labs    rsalz@bbn.com
  1174. Moderator, comp.sources.unix    sources@uunet.uu.net
  1175.